package com.jy.modules.cims.deal.service;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import com.jy.modules.cims.common.CimsConstant;
import com.jy.modules.cims.common.exception.CimsExceptionConstant;
import com.jy.modules.cims.common.exception.InteractException;
import com.jy.modules.cims.data.common.dao.TCMmCreditDealDetailDao;
import com.jy.modules.cims.data.common.dao.TCMmCreditDetailDao;
import com.jy.modules.cims.data.common.dao.TCMmCreditTimeoutDao;
import com.jy.modules.cims.data.common.dto.TCMmCreditDetailDTO;
import com.jy.modules.cims.data.common.dto.TCMmCreditPackageDTO;
import com.jy.modules.cims.data.common.dto.TCMmCreditTimeoutDTO;
import com.jy.modules.cims.data.dto.ConfirmParamDto;
import com.jy.modules.cims.data.dto.CreditDetailDto;
import com.jy.modules.cims.data.dto.DealDto;
import com.jy.modules.cims.data.dto.QuotaDetailUnlockParamDto;
import com.jy.modules.cims.interact.ICInteract;
import com.jy.modules.cims.interact.IInteractAssist;

@Service("com.jy.modules.cims.deal.service.TransferConfirmService")
public class TransferConfirmService implements Serializable {
	private static final long serialVersionUID = 1L;

	private static final Logger logger = LoggerFactory.getLogger(TransferConfirmService.class);
	
	@Autowired
	private TCMmCreditTimeoutDao timeoutDao;
	
	@Autowired
	public TCMmCreditDealDetailDao creditDealDetailDao;

	@Autowired
	private TCMmCreditDetailDao creditDetailDao;
	
	@Autowired
	@Qualifier("com.jy.modules.cims.deal.service.TimeoutService")
	private TimeoutService timeoutService;
	
	@Autowired
	@Qualifier("com.jy.modules.cims.interact.CInteractAssist")
	public IInteractAssist iInteractAssist;

	@Autowired
	@Qualifier("com.jy.modules.cims.interact.CCInteractImpl")
	public ICInteract iCInteract;
	
	/**
	 * 转让确认 
	 * @param busiNoForInteract
	 * @param cooperorgCode
	 * @param creditAffiliation
	 * @param batchId
	 * @throws Exception
	 */
	public void doTransferConfirm(List<CreditDetailDto> excelList, String cooperorgCode,
			String creditAffiliation, String batchId, String userId) throws Exception {
		DealDto orgAgreeContract = null;
		TCMmCreditPackageDTO packageInfo = null;
		//获取有效转让列表
		List<CreditDetailDto> creditDetailList = getValidateList(excelList);
		if (CollectionUtils.isNotEmpty(creditDetailList)) {
			//校验LIST
			Map<String, Object> checkMap = checkList(cooperorgCode, creditDetailList, batchId);
			orgAgreeContract = (DealDto) checkMap.get("agreement");
			packageInfo = (TCMmCreditPackageDTO) checkMap.get("package");
			//组装报文list
			Map<String, Object> map = packParams(creditDetailList, cooperorgCode, creditAffiliation, batchId);
			//调用核心接口
			//确认
			String frontTransNoConfirm = callInterface4022(map, cooperorgCode, null, creditAffiliation, batchId, userId);
			List<CreditDetailDto> confirmList = (List<CreditDetailDto>) map.get("confirmCredit"); 
			timeoutService.updateInfo(confirmList, batchId, creditAffiliation, cooperorgCode, frontTransNoConfirm);
			//释放
			String frontTransNoRelease = null;
			try {
				frontTransNoRelease = callInterface4021(map, cooperorgCode, null, creditAffiliation, batchId, userId);
			} catch (Exception e) {
				//当释放接口超时，已确认的债权需要拆包
				timeoutService.doSplitPackageTimeout(confirmList, batchId, cooperorgCode, orgAgreeContract, packageInfo);
				throw e;
			}
			List<CreditDetailDto> releaseList = (List<CreditDetailDto>) map.get("releaseCredit"); 
			timeoutService.updateInfo(releaseList, batchId, creditAffiliation, cooperorgCode, frontTransNoRelease);
			
			//对于那些无效的数据，需要更新结算状态
			excelList.removeAll(creditDetailList);
		}
		//更新关系表的三费、结算状态;更新明细表的三费
		timeoutService.updateSettleInfo(excelList, batchId);
		//铜板街拆包
		timeoutService.doSplitPackage(creditDetailList, batchId, cooperorgCode, orgAgreeContract, packageInfo);
		//更新老批次表状态（总笔数、转让总价值、三费之和、总体状态）
		timeoutService.updateBatch(batchId);
		//更新批次表状态（总笔数、转让总价值、三费之和、总体状态）
		timeoutService.updateBatch(excelList);
	}
	
	

	/**
	 * 转让确认（超时的情况）
	 * @param busiNoForInteract
	 * @param cooperorgCode
	 * @param creditAffiliation
	 * @param batchId
	 * @throws Exception
	 */
	public void doTransferConfirmTimeout(String frontTransNo, String creditAffiliation, String userId) throws Exception {
		logger.info("处理转让确认（超时的情况），frontTransNo=" + frontTransNo);
		List<CreditDetailDto> creditDetailList = new ArrayList<CreditDetailDto>();
		Map<String,Object> searchParams = new HashMap<String,Object>();
		TCMmCreditTimeoutDTO param = new TCMmCreditTimeoutDTO();
		param.setFrontTransNo(frontTransNo);
		searchParams.put("dto", param);
		//查询timeout记录表
		List<TCMmCreditTimeoutDTO> timeoutList = timeoutDao.searchTCMmCreditTimeout(searchParams);
		if (CollectionUtils.isEmpty(timeoutList)) {
			logger.info("超时明细记录没有找到，frontTransNo=" + frontTransNo);
			return;
		}
		String batchId = timeoutList.get(0).getDealCode();//批次id
		String cooperorgCode = timeoutList.get(0).getCorpCode();//合作机构编码
		String interfaceNo = timeoutList.get(0).getInterfaceNo();//接口编码
		//从timeoutdto转为detaildto
		for (TCMmCreditTimeoutDTO timeoutDto : timeoutList) {
			CreditDetailDto credit = getDetailFromTimeoutDto(timeoutDto);
			creditDetailList.add(credit);
		}
		//校验LIST
//		checkList(cooperorgCode, creditDetailList);
		//组装报文list
		Map<String, Object> map = packParams(creditDetailList, cooperorgCode, creditAffiliation, batchId);
		//调用核心接口
		//释放
		if ("4021".equals(interfaceNo)) {
			callInterface4021(map, cooperorgCode, frontTransNo, creditAffiliation, batchId, userId);
			List<CreditDetailDto> releaseList = (List<CreditDetailDto>) map.get("releaseCredit"); 
			timeoutService.updateInfo(releaseList, batchId, creditAffiliation, cooperorgCode, frontTransNo);
		} else if ("4022".equals(interfaceNo)) {
			//确认
			callInterface4022(map, cooperorgCode, frontTransNo, creditAffiliation, batchId, userId);
			List<CreditDetailDto> confirmList = (List<CreditDetailDto>) map.get("confirmCredit"); 
			timeoutService.updateInfo(confirmList, batchId, creditAffiliation, cooperorgCode, frontTransNo);
		}
		//铜板街拆包
		if(CimsConstant.TBJ_COOPERORG_CODE.equals(cooperorgCode)){
			DealDto orgAgreeContract = null;
			TCMmCreditPackageDTO packageInfo = null;
			CreditDetailDto creditDetailDto = creditDetailList.get(0);
			String corpPackName = creditDetailDto.getCooperorgPackageName();
			String currPackName = creditDetailDto.getPackageNum();
			if (!currPackName.equals(corpPackName)) {
				//所属包名与机构理财包不同，则拆包
				orgAgreeContract = timeoutService.getOrgAgreeContract(batchId);
				String contractCode = orgAgreeContract.getContractCode();//合约编号
				packageInfo = timeoutService.getPackageInfo(cooperorgCode, corpPackName, contractCode);
				timeoutService.doSplitPackage(creditDetailList, batchId, cooperorgCode, orgAgreeContract, packageInfo);
			}
		}
		//更新老批次表状态（总笔数、转让总价值、三费之和、总体状态）
		timeoutService.updateBatch(batchId);
	}

	
	/**
	 * DTO转换
	 * @param timeoutDto
	 * @return
	 */
	private CreditDetailDto getDetailFromTimeoutDto(TCMmCreditTimeoutDTO timeoutDto) {
		CreditDetailDto credit = new CreditDetailDto();
		credit.setDealCreditorStatus(timeoutDto.getOperStatus());//交互状态
		credit.setCreditCode(timeoutDto.getCreditCode());//债权编号
		credit.setTransferId(timeoutDto.getTransferId());//转让编号
		credit.setThisMakeCreditorValue(timeoutDto.getThisMakeCreditorValue());//本次转让债权价值
		credit.setDeliverDate(timeoutDto.getDeliverDate());//交割日期
		credit.setMakeCreditorValue(timeoutDto.getMakeCreditorValue());//转让债权总价值
		credit.setPlanRedeemDate(timeoutDto.getPlanRedeemDate());//计划赎回日期
		credit.setServiceCharge(timeoutDto.getServiceCharge());//服务费
		credit.setGuaranteeFee(timeoutDto.getGuaranteeFee());//担保费
		credit.setCautionMoney(timeoutDto.getCautionMoney());//保证金
		credit.setPackageNum(timeoutDto.getPackageNum());//包名
		credit.setCooperorgPackageName(timeoutDto.getCooperorgPackageName());//机构理财包
		credit.setCostState(timeoutDto.getSettleStatus());//结算标识
		credit.setCooperorgCode(timeoutDto.getCorpCode());//合作机构编码
		return credit;
	}

	/**
	 * 查询超时的流水号
	 * @param interfaceNo
	 * @return
	 */
	public List<String> queryTimeoutTransNos(String[] interfaceNo) {
		Map<String, Object> paramMap = new HashMap<String, Object>();
		paramMap.put("interfaceNos", interfaceNo);
		return timeoutDao.queryTimeoutTransNos(paramMap);
	}
	
	/**
	 * 获取有效转让列表
	 * 
	 * @param creditDealList
	 * @return
	 * @throws Exception
	 */
	private List<CreditDetailDto> getValidateList(List<CreditDetailDto> creditDealList) throws Exception {
		List<CreditDetailDto> resultRreditDealList = new ArrayList<CreditDetailDto>();
		List<CreditDetailDto> nullList = new ArrayList<CreditDetailDto>();
		for (CreditDetailDto creditDetailDto : creditDealList) {
			//去掉transferId为空的记录，有可能解析excel时会多出一行空行
			if (creditDetailDto.getTransferId() == null) {
				logger.warn("准备剔除转让编号为空的记录 ");
				nullList.add(creditDetailDto);
				continue;
			}
			
			//当交互状态不等于  02已卖出,03  取消  05赎回  返回 空值！
			if (!("02").equals(creditDetailDto.getDealCreditorStatus()) 
					&& !("03").equals(creditDetailDto.getDealCreditorStatus())) {
				logger.warn("跳过不处理，交互状态不是[02-已卖出 03-取消]，此时交互状态为：" + creditDetailDto.getDealCreditorStatus() + "，转让编号=" + creditDetailDto.getTransferId());
				continue;
			}

			//查询明细表
			Map<String, Object> map = new HashMap<String, Object>();
			TCMmCreditDetailDTO dto = new TCMmCreditDetailDTO();
			dto.setTransferId(creditDetailDto.getTransferId());
			map.put("dto", dto);
			List<TCMmCreditDetailDTO> list = creditDetailDao.searchTCMmCreditDetail(map);
			if (CollectionUtils.isEmpty(list)) {
				logger.warn("跳过不处理，债权明细表没有找到记录，转让编号=" + creditDetailDto.getTransferId());
				continue;
			}
			// 当合作机构债权状态 等于 在途（01）
			dto = list.get(0);
			if (!CimsConstant.CREDIT_STATUS_WAY.equals(dto.getCreditorStatus())) {
				logger.warn("跳过不处理，债权明细表状态不是[在途]，此时状态为：" 
						+ dto.getCreditorStatus() +"，转让编号=" + creditDetailDto.getTransferId());
				continue;
			} else {
				//导入的excel可能没有这些列，需要查询明细表，设置value
				creditDetailDto.setPackageNum(dto.getPackageNum());
				creditDetailDto.setCooperorgCode(dto.getCooperorgCode());
				creditDetailDto.setContractSum(dto.getContractSum());
				creditDetailDto.setThisRepaySum(dto.getThisRepaySum());
			}
			//查询超时表
			int count = timeoutDao.queryTimeoutCountByTransferId(creditDetailDto.getTransferId());
			if (count > 0) {
				logger.warn("跳过不处理，超时表存在该转让编号：" + creditDetailDto.getTransferId());
				continue;
			}
			resultRreditDealList.add(creditDetailDto);
		}
		//剔除转让编号为空的记录
		creditDealList.removeAll(nullList);
		
		if (resultRreditDealList.size() > 0) {
			return resultRreditDealList;
		}else{
			return null;
		}

	}
	
	
	/**
	 * 组装报文数据
	 * @param creditDetailList
	 * @param busiNoForInteract
	 * @param cooperorgCode
	 * @param creditAffiliation
	 * @param dealCode
	 * @return
	 */
	private Map<String, Object> packParams(List<CreditDetailDto> creditDetailList, String cooperorgCode,String creditAffiliation,String dealCode) {
		logger.info("组装发送核心报文数据");
		Map<String, Object> map = new HashMap<String, Object>();
		if (creditDetailList.size() > 0) {
			List<QuotaDetailUnlockParamDto.CreditRightUnlockInfo> creditRightUnlockInfoList = new ArrayList<QuotaDetailUnlockParamDto.CreditRightUnlockInfo>();
			List<ConfirmParamDto.CreditRightInfo> creditRightInfoList = new ArrayList<ConfirmParamDto.CreditRightInfo>();
			List<CreditDetailDto> releaseList = new ArrayList<CreditDetailDto>();
			List<CreditDetailDto> confirmList = new ArrayList<CreditDetailDto>();
			
			for (CreditDetailDto creditDetailDto : creditDetailList) {
				if (CimsConstant.CREDIT_STATUS_LOSE.equals(creditDetailDto.getDealCreditorStatus())) {
					QuotaDetailUnlockParamDto.CreditRightUnlockInfo creditRightUnlockInfo = new QuotaDetailUnlockParamDto.CreditRightUnlockInfo();
					creditRightUnlockInfo.setCreditId(creditDetailDto.getCreditCode());// 债权编号
					creditRightUnlockInfo.setTransferId(creditDetailDto.getTransferId());// 转让编号
//					creditRightUnlockInfo.setEachRepaymentValue(creditDetailDto.getThisRepaySum());// //本次释放对应月还金额(本期还款金额)
					creditRightUnlockInfo.setContractNo(creditDetailDto.getCreditCode());
					creditRightUnlockInfo.setFreeValue(creditDetailDto.getThisMakeCreditorValue());// 本次释放债权价值（本次转让债权价值）
					creditRightUnlockInfo.setIsWhole(CimsConstant.CREDIT_ISWHOLE);// 全部释放
					creditRightUnlockInfoList.add(creditRightUnlockInfo);
					releaseList.add(creditDetailDto);
				} else if (CimsConstant.CREDIT_STATUS_WIN.equals(creditDetailDto.getDealCreditorStatus())) {
					ConfirmParamDto.CreditRightInfo creditRightInfo = new ConfirmParamDto.CreditRightInfo();
					creditRightInfo.setCreditId(creditDetailDto.getCreditCode());// 协议编号
					creditRightInfo.setTransferId(creditDetailDto.getTransferId());// 转让编号
//					creditRightInfo.setSureValue(creditDetailDto.getThisMakeCreditorValue());// 本次确认债权价值
//					creditRightInfo.setEachRepaymentValue(creditDetailDto.getThisRepaySum());// 本次确认对应月还金额
					creditRightInfo.setDeliveryDate(creditDetailDto.getDeliverDate());// 交割日期
					creditRightInfo.setContractNo(creditDetailDto.getCreditCode());
					creditRightInfoList.add(creditRightInfo);
					confirmList.add(creditDetailDto);
				}
			}
			map.put("releaseInterface", creditRightUnlockInfoList);
			map.put("confirmInterface", creditRightInfoList);
			map.put("releaseCredit", releaseList);
			map.put("confirmCredit", confirmList);
			logger.info("转让释放条数：" + releaseList.size());
			logger.info("转让确认条数：" + confirmList.size());
		}
		return map;
	}
	
	/**
	 * 债权释放
	 * @param map
	 * @param frontTransNo
	 * @param cooperorgCode
	 * @param creditAffiliation
	 */
	private String callInterface4021(Map<String, Object> map, String cooperorgCode, String frontTransNo,
			String creditAffiliation, String batchId, String userId) {
		List<QuotaDetailUnlockParamDto.CreditRightUnlockInfo> creditRightUnlockInfoList = (List<QuotaDetailUnlockParamDto.CreditRightUnlockInfo>)map.get("releaseInterface");
		if (CollectionUtils.isNotEmpty(creditRightUnlockInfoList)) {
			if (frontTransNo == null) {
				frontTransNo = iInteractAssist.getBusiNoForInteract();
			} 
			QuotaDetailUnlockParamDto paramDto = new QuotaDetailUnlockParamDto();
			paramDto.setQuotaType(CimsConstant.QUOTATYPE_CR);
			paramDto.setCreditRightUnlockList(creditRightUnlockInfoList);
			paramDto.setDealCode(frontTransNo);
			// 调用释放债权的接口
			try {
				logger.info("调用转让释放接口4021开始：frontTransNo=" + frontTransNo);
				iCInteract.quotaDetailUnlock(paramDto); 
				logger.info("调用转让释放接口4021成功：frontTransNo=" + frontTransNo);
			} catch (InteractException e) {
				logger.info("调用转让释放接口4021失败：frontTransNo=" + frontTransNo);
				if (e.getMessage().contains(CimsExceptionConstant.INTERACT_NETWORK_ERROR)) {
					//保存timeout记录表
					List<CreditDetailDto> releaseList = (List<CreditDetailDto>) map.get("releaseCredit"); 
				  	for (CreditDetailDto releaseDto : releaseList) {
				  		timeoutService.saveTimeoutRecord(releaseDto, frontTransNo, "4021", batchId, userId);
				  	}
				}
				throw e;
			}
		}
		return frontTransNo;
	}
	
	/**
	 * 转让确认
	 * @param map
	 * @param frontTransNo
	 * @param cooperorgCode
	 * @param creditAffiliation
	 */
	private String callInterface4022(Map<String, Object> map, String cooperorgCode, 
			String frontTransNo, String creditAffiliation, String batchId, String userId) {
		List<ConfirmParamDto.CreditRightInfo> creditRightInfoList = (List<ConfirmParamDto.CreditRightInfo>)map.get("confirmInterface");
		if (CollectionUtils.isNotEmpty(creditRightInfoList)) {
			// 债权审批确认
			if (frontTransNo == null) {
				frontTransNo = iInteractAssist.getBusiNoForInteract();
			} 
			ConfirmParamDto confirmParamDto = new ConfirmParamDto();
			confirmParamDto.setBusiType(CimsConstant.QUOTATYPE_CR);
			confirmParamDto.setCreditRightList(creditRightInfoList);
			confirmParamDto.setFrontTransNo(frontTransNo);
			confirmParamDto.setDealCode(batchId);
			confirmParamDto.setCooperorgCode(cooperorgCode);
			confirmParamDto.setCreditAffiliation(creditAffiliation);
			try {
				logger.info("调用转让确认接口4022开始：frontTransNo=" + frontTransNo);
				iCInteract.approveConfrim(confirmParamDto); 
				logger.info("调用转让确认接口4022成功：frontTransNo=" + frontTransNo);
			} catch (InteractException e) {
				logger.info("调用转让确认接口4022失败：frontTransNo=" + frontTransNo);
				if (e.getMessage().contains(CimsExceptionConstant.INTERACT_NETWORK_ERROR)) {
					// 保存timeout记录表
					List<CreditDetailDto> confirmList = (List<CreditDetailDto>) map.get("confirmCredit");
					for (CreditDetailDto confirmDto : confirmList) {
						timeoutService.saveTimeoutRecord(confirmDto, frontTransNo, "4022", batchId, userId);
					}
				}
				throw e;
			}
		}
		return frontTransNo;
	}
	
	
	/**
	 * 校验债权转让导入的债权
	 * @param creditDetailList
	 */
	private Map<String, Object> checkList(String cooperorgCode, List<CreditDetailDto> creditDetailList, String batchId) throws Exception{
		logger.info("校验债权字段信息");
		Map<String, Object> map = new HashMap<String, Object>();
		List<String> cooperorgPackageNames = new ArrayList<String>();
		for (CreditDetailDto creditDetailDto : creditDetailList) {
			if(null==creditDetailDto.getTransferId()){
				throw new RuntimeException("转让编号不能为空！");
			}
			if(null==creditDetailDto.getCreditCode()){
				throw new RuntimeException("债权编号不能为空！");
			}
			if(null==creditDetailDto.getDealCreditorStatus()){
				throw new RuntimeException("交互状态不能为空！");
			}
			if(CimsConstant.CREDIT_STATUS_WIN.equals(creditDetailDto.getDealCreditorStatus())) {
				//债权已卖出的情况
		        if(creditDetailDto.getMakeCreditorValue()==null 
		        		|| creditDetailDto.getMakeCreditorValue().compareTo(BigDecimal.ZERO) <= 0){
					throw new RuntimeException("转让价值必须大于0");
		        }
				if(null==creditDetailDto.getDeliverDate()){
					throw new RuntimeException("交割日期不能为空！");
				}
			}
			if(CimsConstant.TBJ_COOPERORG_CODE.equals(cooperorgCode)){
				if(null==creditDetailDto.getCooperorgPackageName()){
					throw new RuntimeException("机构理财包不能为空！");
				}
				cooperorgPackageNames.add(creditDetailDto.getCooperorgPackageName());
			}
		}
		
		if(CimsConstant.TBJ_COOPERORG_CODE.equals(cooperorgCode)){
			//验证机构理财包是否重复
			Set<String> s = new HashSet<String>(cooperorgPackageNames);
			if (s.size() > 1) {
				throw new RuntimeException("导入excel里的机构理财包号必须相同!");
			}
			
			CreditDetailDto creditDetailDto = creditDetailList.get(0);
			String corpPackName = creditDetailDto.getCooperorgPackageName();
			String currPackName = creditDetailDto.getPackageNum();
			if (!currPackName.equals(corpPackName)) {
				//所属包名与机构理财包不同，则拆包
				DealDto orgAgreeContract = timeoutService.getOrgAgreeContract(batchId);
				if (orgAgreeContract == null) {
					throw new RuntimeException("铜板街拆包时找不到原始包信息，批次号=" + batchId);
				}
				String contractCode = orgAgreeContract.getContractCode();//合约编号
				TCMmCreditPackageDTO packageInfo = timeoutService.getPackageInfo(cooperorgCode, corpPackName, contractCode);
				if (packageInfo != null && !"1".equals(packageInfo.getIsCorpPack())) {
					throw new RuntimeException("机构理财包与我司包名重复，包名=" + corpPackName + "，合约编号=" + contractCode + ",机构编号=" + cooperorgCode);
				}
				map.put("agreement", orgAgreeContract);
				map.put("package", packageInfo);
			}
		}
		return map;
	}
	
}
